package com.weirblog.login;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.weirblog.entity.Users;
import com.weirblog.util.JWTUtil;

import io.quarkus.hibernate.reactive.panache.PanacheEntityBase;
import io.vertx.core.http.Cookie;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.annotation.security.PermitAll;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;

/**
 * Shows how to create a simple OAuth integration.
 *
 * To Use:
 *
 * export CLIENT_ID=XXX export CLIENT_SECRET=XXX mvn compile quarkus:dev
 *
 *
 * in browser navigate to http://6545-117-173-226-142.ngrok.io/oauth/login
 */
@Path("/oauth-github")
public class GithubOauthResource {

	public static class GithubAuthReq {

		@JsonProperty("client_id")
		public String clientId = "f2bb003d1642d62b8cf5";

		@JsonProperty("client_secret")
		public String clientSecret = "2c73a2a6565eefb10b416f5e77021c522b6cfb00";

		@JsonProperty("redirect_url")
		public String redirectUrl = "http://localhost:10802/oauth-github/callback";

		@JsonProperty("scope")
		public String scope = "read:user read:org";

		@JsonProperty("state")
		public String state = "weir";
//        public final String state = UUID.randomUUID().toString();

		@JsonProperty("allow_signup")
		public String allowSignup = "false";

		public GithubAuthReq() {
		}

		public GithubAuthReq(String clientId, String clientSecret) {
			this.clientId = clientId;
			this.clientSecret = clientSecret;
		}

		public URI getAuthorizeUri() {
			return UriBuilder.fromUri("https://github.com/login/oauth/authorize").queryParam("client_id", clientId)
					.queryParam("redirect_url", redirectUrl).queryParam("scope", scope).queryParam("state", state)
					.queryParam("allow_signup", allowSignup).build();
		}

		public URI getCodeUri(String code) {
			return UriBuilder.fromUri("https://github.com/login/oauth/access_token").queryParam("client_id", clientId)
					.queryParam("client_secret", clientSecret).queryParam("redirect_url", redirectUrl)
					.queryParam("code", code).queryParam("state", state).build();
		}

	}

	private Client client = ResteasyClientBuilder.newClient();
	private Map<String, GithubAuthReq> outstandingRequests = new HashMap<>();
	private Map<String, String> accessTokens = new HashMap<>();

	@Context
	HttpServerRequest request;
	@Context
	HttpServerResponse response;

	@Path("/home")
	@Produces(MediaType.APPLICATION_JSON)
	@GET
	public Response home() {
		Set<Cookie> cookies = request.cookies();
		Cookie sessionCookie = null;
		for (Cookie cookie : cookies) {
//			System.out.println("------------------cookie------" + cookie.getName());
			if (cookie.getName().equals("session")) {
				sessionCookie = cookie;
			}
		}
		if (sessionCookie == null) {
			return Response.seeOther(UriBuilder.fromPath("/oauth/login").build()).build();
		}

		String token = accessTokens.get(sessionCookie.getValue());
		final String bearer = "token " + token;
		final String teamsJson = client.target("https://api.github.com/user").request().header("Authorization", bearer)
				.get().readEntity(String.class);
		final String orgsJson = client.target("https://api.github.com/user/orgs").request()
				.header("Authorization", bearer).get().readEntity(String.class);
		return Response.ok().entity("{\"teams\":" + teamsJson + ",\"orgs\":" + orgsJson + "}").build();
	}
	@GET
	@Path("/callback")
	public Response callback(@QueryParam("code") String code, @QueryParam("state") String state) {
//		System.out.println("----------callback --------code----------->" + code);
		GithubAuthReq req = new GithubAuthReq();
		URI codeUri = req.getCodeUri(code);
		WebTarget target = this.client.target(codeUri);
		Response response = target.request().get();
		if (response.getStatus() != 200) {
			System.out.println(response);
			return Response.status(Status.BAD_REQUEST).entity("not accepted by github").build();
		}

		InputStream inputStream = (InputStream) response.getEntity();
		String result = new BufferedReader(new InputStreamReader(inputStream)).lines()
				.collect(Collectors.joining("\n"));
//		System.out.println("result----------->" + result);

		/**
		 * 以 & 为分割字符分割 result
		 */
		String[] githubResultList = result.split("&");
		List<String> params = new ArrayList<>();
		// paramMap 是分割后得到的参数对, 比说 access_token=ad5f4as6gfads4as98fg
		for (String paramMap : githubResultList) {
			if (!"scope".equals(paramMap.split("=")[0])) {
				// 再以 = 为分割字符分割, 并加到 params 中
				params.add(paramMap.split("=")[1]);
			}
		}
		final String bearer = "token " + params.get(0);
		final String teamsJson = client.target("https://api.github.com/user").request().header("Authorization", bearer)
				.get().readEntity(String.class);
//		System.out.println("teamsJson----------->" + teamsJson);
		Map decodeValue = Json.decodeValue(teamsJson, Map.class);
//		System.out.println("decodeValue----------->" + teamsJson);
		List<PanacheEntityBase> users = Users.list("userName=?1 and accountId=?2", decodeValue.get("login"),decodeValue.get("id").toString()).await().indefinitely();
		Users u = null;
		if (users != null && users.size() > 0) {
			u = (Users) users.get(0);
		}else {
			u = new Users();
			u.createDate = new Date();
			u.accountId = decodeValue.get("id").toString();
			u.token = UUID.randomUUID().toString();
			u.userName = decodeValue.get("login").toString();
			u.profileImageUrl = decodeValue.get("avatar_url").toString();
			u.persistAndFlush().await().indefinitely();
		}
//		String ujson = new JsonObject().put("user", u).toString();
//		String token = tokenService.generateToken(u.token, ujson, null);
		String sign = JWTUtil.sign(u.token,u.accountId+"_"+u.userName);
//		this.response.addCookie(Cookie.cookie("weir-token", params.get(0)));
		final String sessionId = UUID.randomUUID().toString();
		accessTokens.put(sessionId, params.get(0));
		return Response.seeOther(UriBuilder.fromPath("/bbs")
				.queryParam("sign", sign)
				.build()).build();
//		return Response.seeOther(UriBuilder.fromPath("/bbs?sign="+sign).build()).build();
	}

	@GET
	@Path("/login")
	@Produces(MediaType.TEXT_HTML)
	public Response login() {
		String clientId = "f2bb003d1642d62b8cf5";
		String client_secret = "2c73a2a6565eefb10b416f5e77021c522b6cfb00";
		GithubAuthReq req = new GithubAuthReq(clientId, client_secret);
		outstandingRequests.put(req.state, req);
		return Response
				.ok(String.format("<body><a href='%s'>click to login with github</a></body>", req.getAuthorizeUri()))
				.build();
	}
}